package com.zc.auth.security.core.configuration;

import com.zc.auth.security.core.access.MonoRoleUrlAccessDecisionManager;
import com.zc.auth.security.core.access.meta.DefaultUrlRoleMetaDataManager;
import com.zc.auth.security.core.access.meta.UrlRoleMetaDataManager;
import com.zc.auth.security.core.configuration.adapter.WebFluxSecurityConfigureAdapter;
import com.zc.auth.security.core.handler.MonoRoleAccessDeniedHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.Map;

/**
 * Webflux认证基础bean加载
 *
 * @author zcj
 * @version 1.0.0
 * @date 2022/1/12 19:19
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@Slf4j
public class WebFluxSecurityConfiguration {

    @Autowired
    private UrlRoleMetaDataManager urlRoleMetaDataManager;

    @Bean
    @ConditionalOnMissingBean(value = ReactiveAuthorizationManager.class)
    public ReactiveAuthorizationManager reactiveAuthorizationManager() {
        return new MonoRoleUrlAccessDecisionManager(urlRoleMetaDataManager);
    }

    @Bean
    @ConditionalOnMissingBean(value = ServerAccessDeniedHandler.class)
    public ServerAccessDeniedHandler serverAccessDeniedHandler() {
        return new MonoRoleAccessDeniedHandler();
    }

    @Bean
    @ConditionalOnMissingBean(value = {WebFluxSecurityConfigureAdapter.class})
    public WebFluxSecurityConfigureAdapter webFluxSecurityConfigureAdapter() {
        return new WebFluxSecurityConfigureAdapter();
    }

    @PostConstruct
    public void initMetaData() {
        if (this.urlRoleMetaDataManager instanceof DefaultUrlRoleMetaDataManager) {
            Map<String, ? extends Collection<String>> map = this.urlRoleMetaDataManager.updateUrlsAndRolesMap();
            log.info(String.format("角色url权限元数据加载完成，共%s条", map == null ? 0 : map.size()));
        }
    }

}
